home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC-GLU / MIPMAP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-18  |  18.7 KB  |  776 lines

  1. /* $Id: mipmap.c,v 1.11 1998/09/18 02:44:03 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.4
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: mipmap.c,v $
  26.  * Revision 1.11  1998/09/18 02:44:03  brianp
  27.  * further changes to gluScaleImage() per Randy Frank
  28.  *
  29.  * Revision 1.10  1998/09/17 03:20:26  brianp
  30.  * fixed another bug in gluScaleImage() per Sven Panne
  31.  *
  32.  * Revision 1.9  1998/07/31 03:06:20  brianp
  33.  * tweaked the gluScaleImage() function per Randy Frank
  34.  *
  35.  * Revision 1.8  1998/07/08 01:02:53  brianp
  36.  * if gluBuildxDMipmaps() width or height <= 0 return GLU_INVALID_VALUE
  37.  *
  38.  * Revision 1.7  1998/07/01 00:18:02  brianp
  39.  * if gluBuildxDMipmaps() width or height <= 0 just return 0
  40.  *
  41.  * Revision 1.6  1998/06/01 01:06:41  brianp
  42.  * small update for Next/OpenStep from Alexander Mai
  43.  *
  44.  * Revision 1.5  1997/07/24 01:28:44  brianp
  45.  * changed precompiled header symbol from PCH to PC_HEADER
  46.  *
  47.  * Revision 1.4  1997/06/23 00:22:56  brianp
  48.  * added dummy() call to work around an MSVC 4.1 bug
  49.  *
  50.  * Revision 1.3  1997/05/28 02:29:38  brianp
  51.  * added support for precompiled headers (PCH), inserted APIENTRY keyword
  52.  *
  53.  * Revision 1.2  1997/05/24 13:32:25  brianp
  54.  * undef EPSILON in case it's already defined
  55.  *
  56.  * Revision 1.1  1996/09/27 01:19:39  brianp
  57.  * Initial revision
  58.  *
  59.  */
  60.  
  61.  
  62. #ifdef PC_HEADER
  63. #include "all.h"
  64. #else
  65. #include <assert.h>
  66. #include <math.h>
  67. #include <stdio.h>
  68. #include <stdlib.h>
  69. #include "gluP.h"
  70. #endif
  71.  
  72.  
  73. /*
  74.  * Compute ceiling of integer quotient of A divided by B:
  75.  */
  76. #define CEILING( A, B )  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
  77.  
  78.  
  79.  
  80. #ifdef EPSILON
  81. #undef EPSILON
  82. #endif
  83. #define EPSILON 0.001
  84.  
  85.  
  86. /* To work around optimizer bug in MSVC4.1 */
  87. #if defined(__WIN32__) && !defined(OPENSTEP)
  88. void dummy(GLuint j, GLuint k){
  89. }
  90. #else
  91. #define dummy(J, K)
  92. #endif
  93.  
  94.  
  95. GLint APIENTRY gluScaleImage( GLenum format,
  96.                               GLint widthin, GLint heightin,
  97.                               GLenum typein, const void *datain,
  98.                               GLint widthout, GLint heightout,
  99.                               GLenum typeout, void *dataout )
  100. {
  101.    GLint components, i, j, k;
  102.    GLfloat *tempin, *tempout;
  103.    GLfloat sx, sy;
  104.    GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
  105.    GLint packrowlength, packalignment, packskiprows, packskippixels;
  106.    GLint sizein, sizeout;
  107.    GLint rowstride, rowlen;
  108.  
  109.  
  110.    /* Determine number of components per pixel */
  111.    switch (format) {
  112.       case GL_COLOR_INDEX:
  113.       case GL_STENCIL_INDEX:
  114.       case GL_DEPTH_COMPONENT:
  115.       case GL_RED:
  116.       case GL_GREEN:
  117.       case GL_BLUE:
  118.       case GL_ALPHA:
  119.       case GL_LUMINANCE:
  120.          components = 1;
  121.      break;
  122.       case GL_LUMINANCE_ALPHA:
  123.      components = 2;
  124.      break;
  125.       case GL_RGB:
  126.      components = 3;
  127.      break;
  128.       case GL_RGBA:
  129.      components = 4;
  130.      break;
  131.       default:
  132.      return GLU_INVALID_ENUM;
  133.    }
  134.  
  135.    /* Determine bytes per input datum */
  136.    switch (typein) {
  137.       case GL_UNSIGNED_BYTE:    sizein = sizeof(GLubyte);    break;
  138.       case GL_BYTE:        sizein = sizeof(GLbyte);    break;
  139.       case GL_UNSIGNED_SHORT:    sizein = sizeof(GLushort);    break;
  140.       case GL_SHORT:        sizein = sizeof(GLshort);    break;
  141.       case GL_UNSIGNED_INT:    sizein = sizeof(GLuint);    break;
  142.       case GL_INT:        sizein = sizeof(GLint);        break;
  143.       case GL_FLOAT:        sizein = sizeof(GLfloat);    break;
  144.       case GL_BITMAP:
  145.      /* not implemented yet */
  146.       default:
  147.      return GL_INVALID_ENUM;
  148.    }
  149.  
  150.    /* Determine bytes per output datum */
  151.    switch (typeout) {
  152.       case GL_UNSIGNED_BYTE:    sizeout = sizeof(GLubyte);    break;
  153.       case GL_BYTE:        sizeout = sizeof(GLbyte);    break;
  154.       case GL_UNSIGNED_SHORT:    sizeout = sizeof(GLushort);    break;
  155.       case GL_SHORT:        sizeout = sizeof(GLshort);    break;
  156.       case GL_UNSIGNED_INT:    sizeout = sizeof(GLuint);    break;
  157.       case GL_INT:        sizeout = sizeof(GLint);    break;
  158.       case GL_FLOAT:        sizeout = sizeof(GLfloat);    break;
  159.       case GL_BITMAP:
  160.      /* not implemented yet */
  161.       default:
  162.      return GL_INVALID_ENUM;
  163.    }
  164.  
  165.    /* Get glPixelStore state */
  166.    glGetIntegerv( GL_UNPACK_ROW_LENGTH, &unpackrowlength );
  167.    glGetIntegerv( GL_UNPACK_ALIGNMENT, &unpackalignment );
  168.    glGetIntegerv( GL_UNPACK_SKIP_ROWS, &unpackskiprows );
  169.    glGetIntegerv( GL_UNPACK_SKIP_PIXELS, &unpackskippixels );
  170.    glGetIntegerv( GL_PACK_ROW_LENGTH, &packrowlength );
  171.    glGetIntegerv( GL_PACK_ALIGNMENT, &packalignment );
  172.    glGetIntegerv( GL_PACK_SKIP_ROWS, &packskiprows );
  173.    glGetIntegerv( GL_PACK_SKIP_PIXELS, &packskippixels );
  174.  
  175.    /* Allocate storage for intermediate images */
  176.    tempin = (GLfloat *) malloc( widthin * heightin
  177.                     * components * sizeof(GLfloat) );
  178.    if (!tempin) {
  179.       return GLU_OUT_OF_MEMORY;
  180.    }
  181.    tempout = (GLfloat *) malloc( widthout * heightout
  182.                       * components * sizeof(GLfloat) );
  183.    if (!tempout) {
  184.       free( tempin );
  185.       return GLU_OUT_OF_MEMORY;
  186.    }
  187.  
  188.  
  189.    /*
  190.     * Unpack the pixel data and convert to floating point
  191.     */
  192.  
  193.    if (unpackrowlength>0) {
  194.       rowlen = unpackrowlength;
  195.    }
  196.    else {
  197.       rowlen = widthin;
  198.    }
  199.    if (sizein >= unpackalignment) {
  200.       rowstride = components * rowlen;
  201.    }
  202.    else {
  203.       rowstride = unpackalignment/sizein
  204.             * CEILING( components * rowlen * sizein, unpackalignment );
  205.    }
  206.  
  207.    switch (typein) {
  208.       case GL_UNSIGNED_BYTE:
  209.      k = 0;
  210.      for (i=0;i<heightin;i++) {
  211.         GLubyte *ubptr = (GLubyte *) datain
  212.                        + i * rowstride
  213.                + unpackskiprows * rowstride
  214.                + unpackskippixels * components;
  215.         for (j=0;j<widthin*components;j++) {
  216.                dummy(j, k);
  217.            tempin[k++] = (GLfloat) *ubptr++;
  218.         }
  219.      }
  220.      break;
  221.       case GL_BYTE:
  222.      k = 0;
  223.      for (i=0;i<heightin;i++) {
  224.         GLbyte *bptr = (GLbyte *) datain
  225.                      + i * rowstride
  226.              + unpackskiprows * rowstride
  227.              + unpackskippixels * components;
  228.         for (j=0;j<widthin*components;j++) {
  229.                dummy(j, k);
  230.            tempin[k++] = (GLfloat) *bptr++;
  231.         }
  232.      }
  233.      break;
  234.       case GL_UNSIGNED_SHORT:
  235.      k = 0;
  236.      for (i=0;i<heightin;i++) {
  237.         GLushort *usptr = (GLushort *) datain
  238.                         + i * rowstride
  239.                 + unpackskiprows * rowstride
  240.                 + unpackskippixels * components;
  241.         for (j=0;j<widthin*components;j++) {
  242.                dummy(j, k);
  243.            tempin[k++] = (GLfloat) *usptr++;
  244.         }
  245.      }
  246.      break;
  247.       case GL_SHORT:
  248.      k = 0;
  249.      for (i=0;i<heightin;i++) {
  250.         GLshort *sptr = (GLshort *) datain
  251.                       + i * rowstride
  252.               + unpackskiprows * rowstride
  253.               + unpackskippixels * components;
  254.         for (j=0;j<widthin*components;j++) {
  255.                dummy(j, k);
  256.            tempin[k++] = (GLfloat) *sptr++;
  257.         }
  258.      }
  259.      break;
  260.       case GL_UNSIGNED_INT:
  261.      k = 0;
  262.      for (i=0;i<heightin;i++) {
  263.         GLuint *uiptr = (GLuint *) datain
  264.                       + i * rowstride
  265.               + unpackskiprows * rowstride
  266.               + unpackskippixels * components;
  267.         for (j=0;j<widthin*components;j++) {
  268.                dummy(j, k);
  269.            tempin[k++] = (GLfloat) *uiptr++;
  270.         }
  271.      }
  272.      break;
  273.       case GL_INT:
  274.      k = 0;
  275.      for (i=0;i<heightin;i++) {
  276.         GLint *iptr = (GLint *) datain
  277.                     + i * rowstride
  278.             + unpackskiprows * rowstride
  279.             + unpackskippixels * components;
  280.         for (j=0;j<widthin*components;j++) {
  281.                dummy(j, k);
  282.            tempin[k++] = (GLfloat) *iptr++;
  283.         }
  284.      }
  285.      break;
  286.       case GL_FLOAT:
  287.      k = 0;
  288.      for (i=0;i<heightin;i++) {
  289.         GLfloat *fptr = (GLfloat *) datain
  290.                       + i * rowstride
  291.               + unpackskiprows * rowstride
  292.               + unpackskippixels * components;
  293.         for (j=0;j<widthin*components;j++) {
  294.                dummy(j, k);
  295.            tempin[k++] = *fptr++;
  296.         }
  297.      }
  298.      break;
  299.       default:
  300.      return GLU_INVALID_ENUM;
  301.    }
  302.  
  303.  
  304.    /*
  305.     * Scale the image!
  306.     */
  307.  
  308.    if (widthout > 1)
  309.       sx = (GLfloat) (widthin-1) / (GLfloat) (widthout-1);
  310.    else
  311.       sx = (GLfloat) (widthin-1);
  312.    if (heightout > 1)
  313.       sy = (GLfloat) (heightin-1) / (GLfloat) (heightout-1);
  314.    else
  315.       sy = (GLfloat) (heightin-1);
  316.  
  317. /*#define POINT_SAMPLE*/
  318. #ifdef POINT_SAMPLE
  319.    for (i=0;i<heightout;i++) {
  320.       GLint ii = i * sy;
  321.       for (j=0;j<widthout;j++) {
  322.      GLint jj = j * sx;
  323.  
  324.      GLfloat *src = tempin + (ii * widthin + jj) * components;
  325.      GLfloat *dst = tempout + (i * widthout + j) * components;
  326.  
  327.      for (k=0;k<components;k++) {
  328.         *dst++ = *src++;
  329.      }
  330.       }
  331.    }
  332. #else
  333.    if (sx<1.0 && sy<1.0) {
  334.       /* magnify both width and height:  use weighted sample of 4 pixels */
  335.       GLint i0, i1, j0, j1;
  336.       GLfloat alpha, beta;
  337.       GLfloat *src00, *src01, *src10, *src11;
  338.       GLfloat s1, s2;
  339.       GLfloat *dst;
  340.  
  341.       for (i=0;i<heightout;i++) {
  342.      i0 = i * sy;
  343.      i1 = i0 + 1;
  344.      if (i1 >= heightin) i1 = heightin-1;
  345. /*     i1 = (i+1) * sy - EPSILON;*/
  346.      alpha = i*sy - i0;
  347.      for (j=0;j<widthout;j++) {
  348.         j0 = j * sx;
  349.         j1 = j0 + 1;
  350.         if (j1 >= widthin) j1 = widthin-1;
  351. /*        j1 = (j+1) * sx - EPSILON; */
  352.         beta = j*sx - j0;
  353.  
  354.         /* compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
  355.         src00 = tempin + (i0 * widthin + j0) * components;
  356.         src01 = tempin + (i0 * widthin + j1) * components;
  357.         src10 = tempin + (i1 * widthin + j0) * components;
  358.         src11 = tempin + (i1 * widthin + j1) * components;
  359.  
  360.         dst = tempout + (i * widthout + j) * components;
  361.  
  362.         for (k=0;k<components;k++) {
  363.            s1 = *src00++ * (1.0-beta) + *src01++ * beta;
  364.            s2 = *src10++ * (1.0-beta) + *src11++ * beta;
  365.            *dst++ = s1 * (1.0-alpha) + s2 * alpha;
  366.         }
  367.      }
  368.       }
  369.    }
  370.    else {
  371.       /* shrink width and/or height:  use an unweighted box filter */
  372.       GLint i0, i1;
  373.       GLint j0, j1;
  374.       GLint ii, jj;
  375.       GLfloat sum, *dst;
  376.  
  377.       for (i=0;i<heightout;i++) {
  378.      i0 = i * sy;
  379.      i1 = i0 + 1;
  380.      if (i1 >= heightin) i1 = heightin-1; 
  381. /*     i1 = (i+1) * sy - EPSILON; */
  382.      for (j=0;j<widthout;j++) {
  383.         j0 = j * sx;
  384.         j1 = j0 + 1;
  385.         if (j1 >= widthin) j1 = widthin-1;
  386. /*        j1 = (j+1) * sx - EPSILON; */
  387.  
  388.         dst = tempout + (i * widthout + j) * components;
  389.  
  390.         /* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
  391.         for (k=0;k<components;k++) {
  392.            sum = 0.0;
  393.            for (ii=i0;ii<=i1;ii++) {
  394.           for (jj=j0;jj<=j1;jj++) {
  395.              sum += *(tempin + (ii * widthin + jj) * components + k);
  396.           }
  397.            }
  398.            sum /= (j1-j0+1) * (i1-i0+1);
  399.            *dst++ = sum;
  400.         }
  401.      }
  402.       }
  403.    }
  404. #endif
  405.  
  406.  
  407.    /*
  408.     * Return output image
  409.     */
  410.  
  411.    if (packrowlength>0) {
  412.       rowlen = packrowlength;
  413.    }
  414.    else {
  415.       rowlen = widthout;
  416.    }
  417.    if (sizeout >= packalignment) {
  418.       rowstride = components * rowlen;
  419.    }
  420.    else {
  421.       rowstride = packalignment/sizeout
  422.             * CEILING( components * rowlen * sizeout, packalignment );
  423.    }
  424.  
  425.    switch (typeout) {
  426.       case GL_UNSIGNED_BYTE:
  427.      k = 0;
  428.      for (i=0;i<heightout;i++) {
  429.         GLubyte *ubptr = (GLubyte *) dataout
  430.                        + i * rowstride
  431.                + packskiprows * rowstride
  432.                + packskippixels * components;
  433.         for (j=0;j<widthout*components;j++) {
  434.                dummy(j, k+i);
  435.            *ubptr++ = (GLubyte) tempout[k++];
  436.         }
  437.      }
  438.      break;
  439.       case GL_BYTE:
  440.      k = 0;
  441.      for (i=0;i<heightout;i++) {
  442.         GLbyte *bptr = (GLbyte *) dataout
  443.                      + i * rowstride
  444.              + packskiprows * rowstride
  445.              + packskippixels * components;
  446.         for (j=0;j<widthout*components;j++) {
  447.                dummy(j, k+i);
  448.            *bptr++ = (GLbyte) tempout[k++];
  449.         }
  450.      }
  451.      break;
  452.       case GL_UNSIGNED_SHORT:
  453.      k = 0;
  454.      for (i=0;i<heightout;i++) {
  455.         GLushort *usptr = (GLushort *) dataout
  456.                         + i * rowstride
  457.                 + packskiprows * rowstride
  458.                 + packskippixels * components;
  459.         for (j=0;j<widthout*components;j++) {
  460.                dummy(j, k+i);
  461.            *usptr++ = (GLushort) tempout[k++];
  462.         }
  463.      }
  464.      break;
  465.       case GL_SHORT:
  466.      k = 0;
  467.      for (i=0;i<heightout;i++) {
  468.         GLshort *sptr = (GLshort *) dataout
  469.                       + i * rowstride
  470.               + packskiprows * rowstride
  471.               + packskippixels * components;
  472.         for (j=0;j<widthout*components;j++) {
  473.                dummy(j, k+i);
  474.            *sptr++ = (GLshort) tempout[k++];
  475.         }
  476.      }
  477.      break;
  478.       case GL_UNSIGNED_INT:
  479.      k = 0;
  480.      for (i=0;i<heightout;i++) {
  481.         GLuint *uiptr = (GLuint *) dataout
  482.                       + i * rowstride
  483.               + packskiprows * rowstride
  484.               + packskippixels * components;
  485.         for (j=0;j<widthout*components;j++) {
  486.                dummy(j, k+i);
  487.            *uiptr++ = (GLuint) tempout[k++];
  488.         }
  489.      }
  490.      break;
  491.       case GL_INT:
  492.      k = 0;
  493.      for (i=0;i<heightout;i++) {
  494.         GLint *iptr = (GLint *) dataout
  495.                     + i * rowstride
  496.             + packskiprows * rowstride
  497.             + packskippixels * components;
  498.         for (j=0;j<widthout*components;j++) {
  499.                dummy(j, k+i);
  500.            *iptr++ = (GLint) tempout[k++];
  501.         }
  502.      }
  503.      break;
  504.       case GL_FLOAT:
  505.      k = 0;
  506.      for (i=0;i<heightout;i++) {
  507.         GLfloat *fptr = (GLfloat *) dataout
  508.                       + i * rowstride
  509.               + packskiprows * rowstride
  510.               + packskippixels * components;
  511.         for (j=0;j<widthout*components;j++) {
  512.                dummy(j, k+i);
  513.            *fptr++ = tempout[k++];
  514.         }
  515.      }
  516.      break;
  517.       default:
  518.      return GLU_INVALID_ENUM;
  519.    }
  520.  
  521.  
  522.    /* free temporary image storage */
  523.    free( tempin );
  524.    free( tempout );
  525.  
  526.    return 0;
  527. }
  528.  
  529.  
  530.  
  531. /*
  532.  * Return the largest k such that 2^k <= n.
  533.  */
  534. static GLint ilog2( GLint n )
  535. {
  536.    GLint k;
  537.  
  538.    if (n<=0) return 0;
  539.    for (k=0; n>>=1; k++) ;
  540.    return k;
  541. }
  542.  
  543.  
  544.  
  545. /*
  546.  * Find the value nearest to n which is also a power of two.
  547.  */
  548. static GLint round2( GLint n )
  549. {
  550.    GLint m;
  551.  
  552.    for (m=1; m<n; m*=2)
  553.      ;
  554.  
  555.    /* m>=n */
  556.    if (m-n <= n-m/2) {
  557.       return m;
  558.    }
  559.    else {
  560.       return m/2;
  561.    }
  562. }
  563.  
  564.  
  565. /*
  566.  * Given an pixel format and datatype, return the number of bytes to
  567.  * store one pixel.
  568.  */
  569. static GLint bytes_per_pixel( GLenum format, GLenum type )
  570. {
  571.    GLint n, m;
  572.  
  573.    switch (format) {
  574.       case GL_COLOR_INDEX:
  575.       case GL_STENCIL_INDEX:
  576.       case GL_DEPTH_COMPONENT:
  577.       case GL_RED:
  578.       case GL_GREEN:
  579.       case GL_BLUE:
  580.       case GL_ALPHA:
  581.       case GL_LUMINANCE:
  582.      n = 1;
  583.      break;
  584.       case GL_LUMINANCE_ALPHA:
  585.      n = 2;
  586.      break;
  587.       case GL_RGB:
  588.      n = 3;
  589.      break;
  590.       case GL_RGBA:
  591.      n = 4;
  592.      break;
  593.       default:
  594.      n = 0;
  595.    }
  596.  
  597.    switch (type) {
  598.       case GL_UNSIGNED_BYTE:    m = sizeof(GLubyte);    break;
  599.       case GL_BYTE:        m = sizeof(GLbyte);    break;
  600.       case GL_BITMAP:        m = 1;            break;
  601.       case GL_UNSIGNED_SHORT:    m = sizeof(GLushort);    break;
  602.       case GL_SHORT:        m = sizeof(GLshort);    break;
  603.       case GL_UNSIGNED_INT:    m = sizeof(GLuint);    break;
  604.       case GL_INT:        m = sizeof(GLint);    break;
  605.       case GL_FLOAT:        m = sizeof(GLfloat);    break;
  606.       default:            m = 0;
  607.    }
  608.  
  609.    return n * m;
  610. }
  611.  
  612.  
  613.  
  614. /*
  615.  * WARNING: This function isn't finished and has never been tested!!!!
  616.  */
  617. GLint APIENTRY gluBuild1DMipmaps( GLenum target, GLint components,
  618.                                   GLint width, GLenum format,
  619.                                   GLenum type, const void *data )
  620. {
  621.    GLubyte *texture;
  622.    GLint levels, max_levels;
  623.    GLint new_width, max_width;
  624.    GLint i, j, k, l;
  625.  
  626.    if (width < 1)
  627.       return GLU_INVALID_VALUE;
  628.  
  629.    glGetIntegerv( GL_MAX_TEXTURE_SIZE, &max_width );
  630.    max_levels = ilog2( max_width ) + 1;
  631.  
  632.    /* Compute how many mipmap images to make */
  633.    levels = ilog2( width ) + 1;
  634.    if (levels>max_levels) {
  635.       levels = max_levels;
  636.    }
  637.  
  638.    new_width = 1 << (levels-1);
  639.  
  640.    texture = (GLubyte *) malloc( new_width * components );
  641.    if (!texture) {
  642.       return GLU_OUT_OF_MEMORY;
  643.    }
  644.  
  645.    if (width != new_width) {
  646.       /* initial rescaling */
  647.       switch (type) {
  648.      case GL_UNSIGNED_BYTE:
  649.         {
  650.            GLubyte *ub_data = (GLubyte *) data;
  651.            for (i=0;i<new_width;i++) {
  652.           j = i * width / new_width;
  653.           for (k=0;k<components;k++) {
  654.              texture[i*components+k] = ub_data[j*components+k];
  655.           }
  656.            }
  657.         }
  658.         break;
  659.      default:
  660.         /* Not implemented */
  661.         return GLU_ERROR;
  662.       }
  663.    }
  664.  
  665.    /* generate and load mipmap images */
  666.    for (l=0;l<levels;l++) {
  667.       glTexImage1D( GL_TEXTURE_1D, l, components, new_width, 0,
  668.             format, GL_UNSIGNED_BYTE, texture );
  669.  
  670.       /* Scale image down to 1/2 size */
  671.       new_width = new_width / 2;
  672.       for (i=0;i<new_width;i++) {
  673.      for (k=0;k<components;k++) {
  674.         GLint sample1, sample2;
  675.         sample1 = (GLint) texture[i*2*components+k];
  676.         sample2 = (GLint) texture[(i*2+1)*components+k];
  677.         texture[i*components+k] = (GLubyte) ((sample1 + sample2) / 2);
  678.      }
  679.       }
  680.    }
  681.  
  682.    free( texture );
  683.  
  684.    /* make sure remaining mipmap levels are removed */
  685.    for (l=levels;l<max_levels;l++) {
  686.       glTexImage1D( GL_TEXTURE_1D, l, components, 0, 0,
  687.             format, GL_UNSIGNED_BYTE, NULL );
  688.    }
  689.  
  690.    return 0;
  691. }
  692.  
  693.  
  694.  
  695. GLint APIENTRY gluBuild2DMipmaps( GLenum target, GLint components,
  696.                                   GLint width, GLint height, GLenum format,
  697.                                   GLenum type, const void *data )
  698. {
  699.    GLint w, h, maxsize;
  700.    void *image, *newimage;
  701.    GLint neww, newh, level, bpp;
  702.    int error;
  703.  
  704.    if (width < 1 || height < 1)
  705.       return GLU_INVALID_VALUE;
  706.  
  707.    glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxsize );
  708.  
  709.    w = round2( width );
  710.    if (w>maxsize) {
  711.       w = maxsize;
  712.    }
  713.    h = round2( height );
  714.    if (h>maxsize) {
  715.       h = maxsize;
  716.    }
  717.  
  718.    bpp = bytes_per_pixel( format, type );
  719.    if (bpp==0) {
  720.       /* probably a bad format or type enum */
  721.       return GLU_INVALID_ENUM;
  722.    }
  723.  
  724.    if (w!=width || h!=height) {
  725.       /* must rescale image to get "top" mipmap texture image */
  726.       image = malloc( (w+4) * h * bpp );
  727.       if (!image) {
  728.      return GLU_OUT_OF_MEMORY;
  729.       }
  730.       error = gluScaleImage( format, width, height, type, data,
  731.                  w, h, type, image );
  732.       if (error) {
  733.      return error;
  734.       }
  735.    }
  736.    else {
  737.       image = (void *) data;
  738.    }
  739.  
  740.    level = 0;
  741.    while (1) {
  742.       glTexImage2D( target, level, components, w, h, 0, format, type, image );
  743.  
  744.       if (w==1 && h==1)  break;
  745.  
  746.       neww = (w<2) ? 1 : w/2;
  747.       newh = (h<2) ? 1 : h/2;
  748.       newimage = malloc( (neww+4) * newh * bpp );
  749.       if (!newimage) {
  750.      return GLU_OUT_OF_MEMORY;
  751.       }
  752.  
  753.       error =  gluScaleImage( format, w, h, type, image,
  754.                   neww, newh, type, newimage );
  755.       if (error) {
  756.      return error;
  757.       }
  758.  
  759.       if (image!=data) {
  760.      free( image );
  761.       }
  762.       image = newimage;
  763.  
  764.       w = neww;
  765.       h = newh;
  766.       level++;
  767.    }
  768.  
  769.    if (image!=data) {
  770.       free( image );
  771.    }
  772.  
  773.    return 0;
  774. }
  775.  
  776.